package com.edu.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.edu.user.domain.dto.AppointmentDetailDTO;
import com.edu.user.domain.dto.AppointmentRequestDTO;
import com.edu.user.domain.dto.NotificationDTO;
import com.edu.user.domain.po.Appointment;
import com.edu.user.domain.po.DoctorSchedule;
import com.edu.user.domain.po.User;
import com.edu.user.domain.vo.AppointmentVO;
import com.edu.user.domain.vo.DoctorVO;
import com.edu.user.mapper.AppointmentMapper;
import com.edu.user.mapper.DoctorScheduleMapper;
import com.edu.user.service.*;
import com.edu.user.utils.BeanUtils;
import com.edu.user.utils.Result;
import com.edu.user.utils.ThreadLocalUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class AppointmentServiceImpl extends ServiceImpl<AppointmentMapper, Appointment> implements AppointmentService {

    private final AppointmentMapper appointmentMapper;
    @Autowired
    DoctorScheduleMapper doctorScheduleMapper;

    @Autowired
    DoctorService doctorService;
    @Autowired
    UserService userService;
    @Autowired
    NotificationService notificationService;


    @Autowired
    public AppointmentServiceImpl(AppointmentMapper appointmentMapper) {
        this.appointmentMapper = appointmentMapper;
    }

    @Override
    public List<AppointmentVO> getAppointmentsByPatient(Long patientId) {
        List<Appointment> appointments = appointmentMapper.selectListByPatientId(patientId);
        List<AppointmentVO>appointmentVOS=new ArrayList<>();
        for (Appointment appointment : appointments) {
            AppointmentVO appointmentVO = BeanUtils.copyProperties(appointment, AppointmentVO.class);
            DoctorSchedule doctorSchedule = doctorScheduleMapper.selectById(appointment.getSchedulesId());
            appointmentVO.setStartTime(doctorSchedule.getStartTime());
            appointmentVO.setEndTime(doctorSchedule.getEndTime());
            appointmentVO.setScheduleDate(doctorSchedule.getScheduleDate());
            DoctorVO doctorVO = doctorService.getDetailById(Math.toIntExact(doctorSchedule.getDoctorId()));
            appointmentVO.setDoctorName(doctorVO.getName());
            appointmentVO.setDepartment(doctorVO.getDepartment());
            appointmentVOS.add(appointmentVO);
        }
        return appointmentVOS;

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result makeAppointment(Long schedulesId) {
        synchronized (this) {
            // 查找对应的排班信息
            DoctorSchedule doctorSchedule = doctorScheduleMapper.selectById(schedulesId);
            if (doctorSchedule == null) {
                return Result.error("找不到对应的排班信息");
            }
            User user = ThreadLocalUtil.get();
            // 检查是否已经有相同的预约记录
            int existingAppointments = appointmentMapper.countByPatientIdAndSchedulesId(user.getId(), schedulesId);
            if (existingAppointments > 0) {
                return Result.error("您已经预约过该医生的这个排班，请勿重复预约");
            }

            // 检查当前预约人数是否已满
            if (doctorSchedule.getCurNum() + 1 > doctorSchedule.getMaxNum()) {
                return Result.error("预约已满");
            }

            // 更新当前人数
            doctorSchedule.setCurNum(doctorSchedule.getCurNum() + 1);
            int updateRows = doctorScheduleMapper.updateById(doctorSchedule);
            if (updateRows <= 0) {
                throw new RuntimeException("更新医生排班表当前人数失败");
            }

            // 创建预约记录

            Appointment appointment = new Appointment();
            appointment.setSchedulesId(schedulesId);
            appointment.setPatientId(user.getId());
            appointment.setDoctorId(doctorScheduleMapper.selectById(schedulesId).getDoctorId());
            appointment.setStatus("待处理"); // 默认状态为待处理
            appointment.setCreatedAt(LocalDateTime.now());
            appointment.setUpdatedAt(LocalDateTime.now());

            int insertRows = appointmentMapper.insert(appointment);
            if (insertRows <= 0) {
                throw new RuntimeException("创建预约记录失败");
            }

            return Result.success("预约成功");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAppointment( Long appointmentId) {
        Appointment appointment = appointmentMapper.selectById(appointmentId);
        if (appointment == null ) {
            return false;
        }
        int rows = appointmentMapper.deleteById(appointmentId);
        if (rows > 0) {
            DoctorSchedule doctorSchedule = doctorScheduleMapper.selectById(appointment.getSchedulesId());
            if (doctorSchedule != null && doctorSchedule.getCurNum() > 0) {
                doctorSchedule.setCurNum(doctorSchedule.getCurNum() - 1);
                doctorScheduleMapper.updateById(doctorSchedule);
            }
            return true;
        } else {
            throw new RuntimeException("删除预约记录失败");
        }
    }
    @Override
    public List<AppointmentDetailDTO> getAppointmentsByDoctor(Long doctorId) {
        List<Appointment> appointments = appointmentMapper.selectListByDoctorId(doctorId);
        List<AppointmentDetailDTO> details = new ArrayList<>();
        for (Appointment appointment : appointments) {
            DoctorSchedule schedule = doctorScheduleMapper.selectById(appointment.getSchedulesId());
            User patient = userService.getById(appointment.getPatientId());
            AppointmentDetailDTO detailDTO = new AppointmentDetailDTO();
            detailDTO.setDoctorId(doctorId);
             detailDTO.setStatus(appointment.getStatus());
            detailDTO.setAppointmentId(appointment.getId());
            detailDTO.setPatientName(patient.getName());
            detailDTO.setPatientGender(patient.getGender());
            detailDTO.setAppointmentDate(schedule.getScheduleDate());
            detailDTO.setStartTime(schedule.getStartTime());
            detailDTO.setEndTime(schedule.getEndTime());
            details.add(detailDTO);
        }
        return details;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result confirmAppointment(Long appointmentId) {

        Appointment appointment = getById(appointmentId);
        if (appointment == null) {
            return Result.error("预约记录不存在");
        }
        appointment.setStatus("已确认");
        appointment.setUpdatedAt(LocalDateTime.now());
        boolean isOK = updateById(appointment);
        if (isOK) {
            //发送通知
            sendNotification("确认",appointment);
            return Result.success("预约确认成功");
        } else {
            throw new RuntimeException("预约确认失败");
        }
    }

    @Override
    public boolean deleteAppointmentByDoctor(Long appointmentId) {
        Appointment appointment = appointmentMapper.selectById(appointmentId);
        if (appointment == null ) {
            return false;
        }
        int rows = appointmentMapper.deleteById(appointmentId);
        if (rows > 0) {
            DoctorSchedule doctorSchedule = doctorScheduleMapper.selectById(appointment.getSchedulesId());
            if (doctorSchedule != null && doctorSchedule.getCurNum() > 0) {
                doctorSchedule.setCurNum(doctorSchedule.getCurNum() - 1);
                doctorScheduleMapper.updateById(doctorSchedule);
            }
            sendNotification("医生取消",appointment);
            return true;
        } else {
            throw new RuntimeException("删除预约记录失败");
        }
    }

    @Override
    public void sendNotification(String status, Appointment appointment) {
        User patient = userService.getById(appointment.getPatientId());
        NotificationDTO notificationDTO = new NotificationDTO();
        notificationDTO.setUserId(patient.getId());
        DoctorSchedule doctorSchedule = doctorScheduleMapper.selectById(appointment.getSchedulesId());
        DoctorVO doctorVO = doctorService.getDetailById(Math.toIntExact(doctorSchedule.getDoctorId()));
        notificationDTO.setMessage("您的预约:"+doctorVO.getDepartment()+" "+doctorVO.getName()+" "+doctorSchedule.getScheduleDate()+" "+doctorSchedule.getStartTime()+"-"+doctorSchedule.getEndTime()+" 已被"+status+"。");
        notificationService.sendNotification(notificationDTO);
    }



   /* @Override
    @Transactional(rollbackFor = Exception.class)
    public Result cancelAppointment(Long appointmentId) {
        Appointment appointment = appointmentMapper.selectById(appointmentId);
        if (appointment == null) {
            return Result.error("预约记录不存在");
        }
        int rows = appointmentMapper.deleteById(appointmentId);
        if (rows > 0) {
            DoctorSchedule doctorSchedule = doctorScheduleMapper.selectById(appointment.getSchedulesId());
            if (doctorSchedule != null && doctorSchedule.getCurNum() > 0) {
                doctorSchedule.setCurNum(doctorSchedule.getCurNum() - 1);
                doctorScheduleMapper.updateById(doctorSchedule);
            }
            return Result.success("预约取消成功");
        } else {
            throw new RuntimeException("预约取消失败");
        }
    }*/

//    @Override
//    @Transactional
//    public boolean makeAppointment(Long patientId, Long schedulesId, String symptoms) {
//        Appointment appointment = new Appointment();
//        appointment.setPatientId(patientId);
//        appointment.setSchedulesId(schedulesId);
//        appointment.setStatus("待处理"); // 默认状态为待处理
//        appointment.setSymptoms(symptoms);
//        appointment.setCreatedAt(LocalDateTime.now());
//        appointment.setUpdatedAt(LocalDateTime.now());
//
//        int rows = appointmentMapper.insert(appointment);
//        return rows > 0;
//    }
}
